package qos.estimator.jdbc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import qos.estimator.statistics.SystemStatisticsCollector;
import qos.estimator.tpch.TPCHQueries;

public class QoSConnectionHandlerThread extends Thread {

	private Socket clientSocket;
	private Map<Integer, String> tpchQueries = new HashMap<Integer, String>();
	private SystemStatisticsCollector statisticsCollector;
	private AtomicInteger numberOfConcurrentTransactions;
	private int queryNumber;

	public QoSConnectionHandlerThread(Socket clientSocket,
			SystemStatisticsCollector statisticsCollector,
			AtomicInteger numberOfConcurrentTransactions) {
		this.statisticsCollector = statisticsCollector;
		this.numberOfConcurrentTransactions = numberOfConcurrentTransactions;
		this.clientSocket = clientSocket;
		tpchQueries.put(0, TPCHQueries.q0);
		tpchQueries.put(1, TPCHQueries.q1);
		tpchQueries.put(2, TPCHQueries.q2);
		tpchQueries.put(3, TPCHQueries.q3);
		tpchQueries.put(4, TPCHQueries.q4);
		tpchQueries.put(5, TPCHQueries.q5);
		tpchQueries.put(6, TPCHQueries.q6);
		tpchQueries.put(7, TPCHQueries.q7);
		tpchQueries.put(8, TPCHQueries.q8);
		tpchQueries.put(9, TPCHQueries.q9);
		tpchQueries.put(10, TPCHQueries.q10);
		tpchQueries.put(11, TPCHQueries.q11);
		tpchQueries.put(12, TPCHQueries.q12);
		tpchQueries.put(13, TPCHQueries.q13);
		tpchQueries.put(14, TPCHQueries.q14);
		tpchQueries.put(15, TPCHQueries.q15);
		tpchQueries.put(16, TPCHQueries.q16);
		tpchQueries.put(17, TPCHQueries.q17);
		tpchQueries.put(18, TPCHQueries.q18);
		tpchQueries.put(19, TPCHQueries.q19);
		tpchQueries.put(20, TPCHQueries.q20);
		tpchQueries.put(21, TPCHQueries.q21);
		tpchQueries.put(22, TPCHQueries.q22);
	}

	protected Statement getStatement() {
		try {
			Class.forName("org.postgresql.Driver");
			Connection conn = DriverManager.getConnection(
					"jdbc:postgresql://localhost/tpch", "tpch", "tpch");
			return conn.createStatement();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return null;
	}

	@Override
	public void run() {
		try {
			PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
					true);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					clientSocket.getInputStream()));

			String sqlQuery;

			while ((sqlQuery = in.readLine()) != null) {

				queryNumber = Integer.parseInt(sqlQuery);
				String query = tpchQueries.get(queryNumber);
				Statement stmt = getStatement();
				try {
					String statistics = statisticsCollector.getLine();
					long elapsedTime = System.currentTimeMillis();
					int numOfQueries = numberOfConcurrentTransactions
							.incrementAndGet();
					stmt.execute(query);
					numberOfConcurrentTransactions.decrementAndGet();
					elapsedTime   = System.currentTimeMillis() - elapsedTime;
					statistics += "\t" + sqlQuery + "\t" + numOfQueries + "\t"
							+ elapsedTime;
					
					stmt.close();
					stmt.getConnection().close();
					System.out.println(statistics);
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}

			out.close();
			in.close();
			clientSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
